﻿#define _CRT_SECURE_NO_WARNINGS  1
#pragma warning(disable:6031)

//课堂随练
//#include<stdio.h>
//#define MAX 100
//int main()
//{
//#if !defined(MAX)
//	printf("100");
//#endif
//	return 0;
//}


//写一个宏，计算结构体中某变量相对于首地址的偏移，并给出说明
//考察：offsetof宏的实现
//offsetof (type,member)
//Return member offset

//#include<stdio.h>
//#define OFFSETOF(type, member) (size_t)(&((type*)0)->member)
//
//struct S
//{
//	int a;
//	char b;
//	short c;
//};
//int main()
//{
//	struct S s = { 0 };
//	printf("%zd\n", OFFSETOF(struct S, a));
//	printf("%zd\n", OFFSETOF(struct S, b));
//	printf("%zd\n", OFFSETOF(struct S, c));
//	return 0;
//}


//写一个宏，可以将一个整数的二进制位的奇数位和偶数位交换。

//#include<stdio.h>
//#define SwapIntBit(n) (((n) & 0x55555555) << 1 | ((n) & 0xaaaaaaaa) >> 1)//n的值不变
//#define SWAP_ODD_EVEN_BIT(n) n = ((((n) & 0x55555555) << 1) + (((n) & 0xaaaaaaaa) >> 1)) //将值赋给n，n改变

//交换奇偶位，需要先分别拿出奇偶位。既然是宏，分别拿出用循环不是很现实，那就用&这些位的方式来做。
//奇数位拿出，那就是要&上010101010101……，偶数位拿出，就是要&上101010101010……，对应十六进制分别是555……和aaa……，
//一般我们默认是32位整数，4位对应一位16进制就是8个5，8个a。通过& 0x55555555的方式拿出奇数位和& 0xaaaaaaa的方式拿出偶数位。
//奇数位左移一位就到了偶数位上，偶数位右移一位就到了奇数位上，最后两个数字或起来，就完成了交换。(要根据自己设置奇偶位的方式来灵活转换)
//※这个宏只能完成32位以内的整形，要想完成64位的，那就将5和a的数量翻倍即可。
//
//int main()
//{
//	int a = 10;
//	int b = 10;
//	printf("%d\n", a);
//	printf("%d\n", SwapIntBit(a));
//
//
//	printf("%d\n", b);
//	SWAP_ODD_EVEN_BIT(b);
//	printf("%d\n", b);
//	return 0;
//}




//进阶测评
//描述
//Fibonacci数列是这样定义的：
//F[0] = 0
//F[1] = 1
//for each i ≥ 2: F[i] = F[i - 1] + F[i - 2]
//因此，Fibonacci数列就形如：0, 1, 1, 2, 3, 5, 8, 13, ...，在Fibonacci数列中的数我们称为Fibonacci数。给你一个N，你想让其变为一个Fibonacci数，
// 每一步你可以把当前数字X变为X - 1或者X + 1，现在给你一个数N求最少需要多少步可以变为Fibonacci数。
//输入描述：
//输入为一个正整数N(1 ≤ N ≤ 1, 000, 000)
//输出描述：
//输出一个最小的步数变为Fibonacci数"


//#include<stdio.h>
//#include<math.h>
//int main()
//{
//    int n = 0;
//    scanf("%d", &n);
//    int a = 0;
//    int b = 1;
//    int c = 0;
//    while (1)
//    {
//        if (n == b)
//        {
//            printf("0");
//            break;
//        }
//        if (n < b)//说明n在a和b之间
//        {
//           /* if (abs(n - a) > abs(n - b))
//            {
//                printf("%d", abs(n - b));
//            }
//            else
//            {
//                printf("%d", abs(n - a));
//            }*/
//            if ((n - a) > (b - n))
//            {
//                printf("%d", b - n);
//            }
//            else
//            {
//                printf("%d", n - a);
//            }
//            break;
//        }
//        c = a + b;
//        a = b;
//        b = c;
//    }
//    return 0;
//}

////描述
//请实现一个函数，将一个字符串s中的每个空格替换成“ % 20”。
//例如，当字符串为We Are Happy.则经过替换之后的字符串为We % 20Are % 20Happy。
//数据范围 :
//0≤𝑙𝑒𝑛(𝑠)≤1000，保证字符串中的字符为大写英文字母、小写英文字母和空格中的一种。
#include<stdio.h>
#include<string.h>


//该方法在牛客网的用例通过8/9，存在小错误（具体啥我也没看出来）害！
//char* replaceSpace(char* s) 
//{
//    char* ret = s;
//    int len = (int)strlen(s);
//    while (*s != '\0')
//    {
//        if (*s == ' ')
//        {
//            int i = 0;
//            while ((s + len - 1 - i) >= (s + 1))
//            {
//                //*(s + len - 1 + 3) = '\0';//不必要，因为字符串会把未初始化的置为'\0';
//                *(s + len - 1 + 2 - i) = *(s + len - 1 - i);
//                i++;
//            }
//            *s = '%';
//            *(s + 1) = '2';
//            *(s + 2) = '0';
//        }
//        s++;
//    }
//    return ret;
//}
// 
// 
// 
// 
//(不知道为啥牛客网上又没完全通过）
//char* replaceSpace(char* s) 
//{
//    // write code here
//    char* ret = s;
//    int len = (int)strlen(s);
//    int count = 0;
//    //数空格
//    while (*s)
//    {
//        if (*s == ' ')
//           count++;
//        s++;
//    }
//    char* end1 = ret + len - 1;
//    char* end2 = ret + len - 1 + count * 2;
//    while (ret <= end1)
//    {
//        if (*end1 != ' ')
//        {
//            *(end2--) = *(end1--);
//           /* end2--;
//            end1--;*/
//        }
//        else
//        {
//            *(end2--) = '0';
//            //end--;//直接在前面表达式--
//            *(end2--) = '2';
//            *(end2--) = '%';
//            end1--;
//        }
//    }
//    return ret;
//}


//跟着老师的方法：牛客网也是8/9通过，我很无语
//char* replaceSpace(char* s)
//{
//    // write code here
//    char* ret = s;
//    int len = (int)strlen(s);
//    int count = 0;
//    //数空格
//    while (*s)
//    {
//        if (*s == ' ')
//            count++;
//        s++;
//    }
//    int end1 = len - 1;
//    int end2 = len - 1 + count * 2;
//    while (end1 != end2)
//    {
//        if (s[end1] != ' ')
//        {
//            s[end2--] = s[end1--];
//            /* end2--;
//             end1--;*/
//        }
//        else
//        {
//            s[end2--] = '0';
//            //end--;//直接在前面表达式--
//            s[end2--] = '2';
//            s[end2--] = '%';
//            end1--;
//        }
//    }
//    return ret;
//}


////方法2：用新的数组接收
//char* replaceSpace(char* s) 
//{
//    int i = 0, j = 0;
//    int cnt = 0, n = strlen(s);
//    for (i = 0; i < n; i++) 
//    {
//        if (s[i] == ' ')
//            cnt++;  //求空格个数
//    }
//    char* ret = NULL;  //新数组头指针
//    ret = (char*)malloc(sizeof(int) * (n + cnt * 3 + 1)); //定义新数组大小
// //要free
//    for (i = 0, j = 0; i < n; i++, j++) 
//    {
//        if (s[i] != ' ')
//            ret[j] = s[i];  //不是空格就直接复制
//        else if (s[i] == ' ') 
//        {
//            ret[j] = '%';   //遇到空格要逐一赋值
//            ret[j + 1] = '2';
//            ret[j + 2] = '0';
//            j = j + 2;  //要与i保持同步
//        }
//    }
//    return ret;
//}


int main()
{
	char s[20] = "   ";
    char* ret = replaceSpace(s);
    printf("%s", ret);
	return 0;
}